{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Document & Document Loaders"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**참고**\n",
    "\n",
    "- [LangChain 에서 사용되는 주요 로더](https://python.langchain.com/v0.1/docs/modules/data_connection/document_loaders/)\n",
    "- [LangChain 에서 사용되는 로더 목록](https://python.langchain.com/v0.1/docs/integrations/document_loaders/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 실습에 활용한 문서\n",
    "\n",
    "소프트웨어정책연구소(SPRi) - 2023년 12월호\n",
    "\n",
    "- 저자: 유재흥(AI정책연구실 책임연구원), 이지수(AI정책연구실 위촉연구원)\n",
    "- 링크: https://spri.kr/posts/view/23669\n",
    "- 파일명: `SPRI_AI_Brief_2023년12월호_F.pdf`\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Document\n",
    "\n",
    "LangChain 의 기본 문서 객체입니다.\n",
    "\n",
    "**속성**\n",
    "- `page_content`: 문서의 내용을 나타내는 문열입니다.\n",
    "- `metadata`: 문서의 메타데이터를 나타내는 딕셔너리입니다.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.documents import Document\n",
    "\n",
    "document = Document(page_content=\"안녕하세요? 이건 랭체인의 도큐먼드 입니다\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 도큐먼트의 속성 확인\n",
    "document.__dict__"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "metadata 에 속성 추가"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 메타데이터 추가\n",
    "document.metadata[\"source\"] = \"TeddyNote\"\n",
    "document.metadata[\"page\"] = 1\n",
    "document.metadata[\"author\"] = \"Teddy\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 도큐먼트의 속성 확인\n",
    "document.metadata"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Document Loader\n",
    "\n",
    "다양한 파일의 형식으로부터 불러온 내용을 문서(Document) 객체로 변환하는 역할을 합니다.\n",
    "\n",
    "### 주요 Loader \n",
    "- PyPDFLoader: PDF 파일을 로드하는 로더입니다.\n",
    "- CSVLoader: CSV 파일을 로드하는 로더입니다.\n",
    "- UnstructuredHTMLLoader: HTML 파일을 로드하는 로더입니다.\n",
    "- JSONLoader: JSON 파일을 로드하는 로더입니다.\n",
    "- TextLoader: 텍스트 파일을 로드하는 로더입니다.\n",
    "- DirectoryLoader: 디렉토리를 로드하는 로더입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 예제 파일 경로\n",
    "FILE_PATH = \"./data/SPRI_AI_Brief_2023년12월호_F.pdf\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_community.document_loaders import PyPDFLoader\n",
    "\n",
    "# 로더 설정\n",
    "loader = PyPDFLoader(FILE_PATH)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### load()\n",
    "\n",
    "- 문서를 로드하여 반환합니다.\n",
    "- 반환된 결과는 `List[Document]` 형태입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# PDF 로더\n",
    "docs = loader.load()\n",
    "\n",
    "# 로드된 문서의 수 확인\n",
    "len(docs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 첫번째 문서 확인\n",
    "docs[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### load_and_split()\n",
    "\n",
    "- splitter 를 사용하여 문서를 분할하고 반환합니다.\n",
    "- 반환된 결과는 `List[Document]` 형태입니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "# 문열 분할기 설정\n",
    "text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=0)\n",
    "\n",
    "# 예제 파일 경로\n",
    "FILE_PATH = \"./data/SPRI_AI_Brief_2023년12월호_F.pdf\"\n",
    "\n",
    "# 로더 설정\n",
    "loader = PyPDFLoader(FILE_PATH)\n",
    "\n",
    "# 문서 분할\n",
    "split_docs = loader.load_and_split(text_splitter=text_splitter)\n",
    "\n",
    "# 로드된 문서의 수 확인\n",
    "print(f\"문서의 길이: {len(split_docs)}\")\n",
    "\n",
    "# 첫번째 문서 확인\n",
    "split_docs[10]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### lazy_load()\n",
    "\n",
    "- generator 방식으로 문서를 로드합니다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "loader.lazy_load()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# generator 방식으로 문서 로드\n",
    "for doc in loader.lazy_load():\n",
    "    print(doc.metadata)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### aload()\n",
    "\n",
    "- 비동기(Async) 방식의 문서 로드"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 문서를 async 방식으로 로드\n",
    "adocs = loader.aload()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 문서 로드\n",
    "await adocs"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
